var http = require("http");
var url = require("url");
var sys = require("sys");

var numberOfClientRequests = 5;
var durationOfProcessing = 2000;
var bodyLength = 10;
var numberOfServerConnections = 2;
var realPrefix = "http://tirion.zemris.fer.hr:9899";

var serviceClientHost = "tirion.zemris.fer.hr";
var serviceClientPort = 9899;
var serviceClientPath = "/testing/abc";

var serviceServerHost = "tirion.zemris.fer.hr";
var serviceServerPort = 9898;
var serviceServerPath = "/";
var pathRegex = "/testing.*";

var applicationBody = "";

for(var i=0; i<bodyLength; i++) {
  applicationBody += "x";
}

var testServerResponse = {body : 'yo', headers : {"content-length" : 2, "access-control-allow-origin" : '*'}, statusCode : 200, reasonPhrase : 'OK', httpVersion :"HTTP/1.1" };

// server part
function registerService() {
  logger("SERVER - Starting REGISTER request.");
  var serverConnection = http.createClient(serviceServerPort, serviceServerHost);
  var revHttpRequest = { Method : "REGISTER", pathRegex : pathRegex };
  var serverRequest = serverConnection.request("POST", serviceServerPath, {"host": serviceServerHost,"x-revhttp" : escape(JSON.stringify(revHttpRequest))});
  
  serverRequest.addListener('response', function (serverResponse) {
    logger("SERVER - Received response to REGISTER request.");
    serverResponse.setBodyEncoding("utf8");
    serverResponse.addListener("end", function () {
      if (serverResponse.statusCode !== 404) {
        logger("SERVER - Response to REGISTER request xrevhttp header: " + unescape(serverResponse.headers["x-revhttp"]));
        var revHttpResponse = JSON.parse(unescape(serverResponse.headers["x-revhttp"]));
        if (revHttpResponse.Method !== "REGISTER-RESPONSE" || revHttpResponse.pathRegex !== pathRegex || revHttpResponse.realPrefix !== realPrefix) { 
          logger("SERVER - Register response is not valid.");
          return;
        } else {
          logger("SERVER - Register response is valid, starting server connections.");
          for (var i=0; i<numberOfServerConnections; i++) {
            createServerConnection();
          }
        }
      } else {
        logger("SERVER - Register response is 404.");
      }
    });
  });
  serverRequest.close();
  logger("SERVER - Register requests sent: ");// + JSON.stringify(serverRequest));
}

function unregisterService() {
  var serverConnection = http.createClient(serviceServerPort, serviceServerHost);
  var revHttpRequest = { Method : "UNREGISTER", pathRegex : pathRegex };
  var serverRequest = serverConnection.request("POST", serviceServerPath, {"host": serviceServerHost,"x-revhttp" : escape(JSON.stringify(revHttpRequest))});
  
  serverRequest.addListener('response', function (serverResponse) {
    serverResponse.setBodyEncoding("utf8");
    serverResponse.addListener("end", function () {
      if (serverResponse.statusCode !== 404) {
        var revHttpResponse = JSON.parse(unescape(serverResponse.headers["x-revhttp"]));
        if (revHttpResponse.Method !== "UNREGISTER-RESPONSE" || revHttpResponse.pathRegex !== pathRegex) { 
          return; // log error
        } else {
          return; // log
        }
      }
    });
  });
  serverRequest.close();
}

function createServerConnection(requestID, response) {
  logger("Starting server connection request.");
  var serverConnection = http.createClient(serviceServerPort, serviceServerHost);
  serverConnection.setTimeout(0);
  serverConnection.addListener("end", function() {
    logger("Server connection ended.");
  });
  
  var revHttpRequest = { Method : typeof requestID === "undefined" ? "REQUEST" : "RESPONSE", pathRegex : pathRegex };
  var serverRequest = null;
  
  if (typeof requestID !== "undefined") {
    revHttpRequest.RequestID = requestID;
    var body = JSON.stringify(response);
    serverRequest = serverConnection.request("POST", serviceServerPath, {"host": serviceServerHost, "Content-Length" : body.length, "x-revhttp" : escape(JSON.stringify(revHttpRequest))});
    serverRequest.write(body, encoding="utf8");
  } else {
    serverRequest = serverConnection.request("POST", serviceServerPath, {"host": serviceServerHost, "x-revhttp" : escape(JSON.stringify(revHttpRequest))});
  }
  serverRequest.addListener('response', function (serverResponse) {
    logger("Server connection response received.");
    serverResponse.setBodyEncoding("utf8");
    serverResponse.body = "";
    serverResponse.addListener("data", function (chunk) { serverResponse.body += chunk; });
    serverResponse.addListener("end", function () {
      logger("Server connection response fully received: ");// + JSON.stringify(serverResponse));
      if (serverResponse.statusCode !== 404) {
        var revHttpResponse = JSON.parse(unescape(serverResponse.headers["x-revhttp"]));
        if (revHttpResponse.pathRegex === pathRegex) {
          logger("Server connection response is OK.");
          setTimeout( function() {
            createServerConnection(revHttpResponse.RequestID, testServerResponse);
          }, durationOfProcessing);
        } else {
          logger("Server connection response has wrong path regex.");
          return;
        }
      } else {
        logger("Server connection response is 404.");
      }      
    });
  });
  serverRequest.close();
  logger("Server connection request sent: ");// + JSON.stringify(serverRequest));
}

registerService();

// client part
setTimeout( function() {
  logger("Starting client requests.");
  var tests = [];
  tests.finish = function() {
    this.remaining -=1;
    if (this.remaining === 0) {
      sys.puts(JSON.stringify(this));
      return;
    }
  }
  tests.remaining = numberOfClientRequests;

  for (var i=0; i<numberOfClientRequests; i++) {
    var test = {};
    tests.push(test);
    test.reqNum = i.toString();
    test.startDate = new Date();
    logger("Starting request: " + test.reqNum);
    var clientConnection = http.createClient(serviceClientPort, serviceClientHost);
    clientConnection.setTimeout(60000);
    
    var clientRequest = clientConnection.request("POST", serviceClientPath, {"host": serviceClientHost, "Content-Length" : bodyLength});
    
    clientRequest.write(applicationBody);
    clientRequest.addListener('response', function(currentTest) {
      return function (clientResponse) {
        logger("Received response for request: " + JSON.stringify(currentTest));
        clientResponse.setBodyEncoding("utf8");
        clientResponse.body = "";
        clientResponse.addListener("data", function (chunk) { clientResponse.body += chunk; });
        clientResponse.addListener("end", function () {
          currentTest.endDate = new Date();
          //test.request = JSON.stringify(clientRequest);
          //test.response = JSON.stringify(clientResponse);
          logger("Received full response for request " + JSON.stringify(currentTest));//+ test.reqNum + ": " + JSON.stringify(clientResponse));
          tests.finish();
        });
      };
    }(test));
    
  clientRequest.close();
  //logger("Request: " + test.reqNum + " sent: " + JSON.stringify(clientRequest));
  }
}, 5000 );